using System;
using System.IO;
using ssh;
using dotnet;
using wspace;
using Renci.SshNet.Common;

namespace command
{
    public class Pull : Cmd
    {
        public Pull ()
        {
            this.Command = "pull";
            this.NeedArg = false;
            this.IsWorkAreaCmd = true;
            this.Discript = "Download files from the server repository.";
            this.Format = "pull [-a,-m]";
            this.Function = Func;
        }

        private void Func(string[] args)
        {
            if (args.Length != 1 && args.Length != 2)
            {
                Utils.ErrorFormat(this.Format);
                return;
            }
            if (args.Length == 2)
            {
                if (!args[1].Equals("-a") && !args[1].Equals("-m"))
                {
                    Utils.ErrorFormat(this.Format);
                    return;
                }
            }

            ServerInfo sinfo = ServerInfo.GetByConfig(this.Data + Utils.GetSlash() + Configs.ConfigName);
            if (sinfo == null) return;
            SftpConnect brg = new SftpConnect(sinfo);
            if (!brg.Connect()) return;
            sinfo.dir = sinfo.dir.Replace('\\', '/');
            if (sinfo.dir.EndsWith('/')) sinfo.dir = sinfo.dir.Substring(0, sinfo.dir.Length - 1);
            if (!brg.sftp.Exists(sinfo.dir))
            {
                Utils.ErrorLog("The remote folder does not exist.");
                brg.DisConnect();
                return;
            }
            string localpath = Directory.GetParent(this.Data).FullName;
            LocalCmp lcmp = new LocalCmp(brg, sinfo.dir, localpath);
            if (!lcmp.CmpLocalDiff()) return;
            ServerCmp scmp = new ServerCmp(brg, sinfo.dir, localpath);
            if (!scmp.CmpServerDiff(lcmp.LignoreList)) return;
            brg.DisConnect();
            if (scmp.RnewFList.Count == 0 && scmp.RmodifyList.Count == 0)
            {
                Utils.MessageLog("There are no new or modified files in the remote repository.");
                return;
            }

            ScpConnect scpcnt = new ScpConnect(sinfo);
            if (!scpcnt.Connect()) return;
            scpcnt.scp.Downloading += new EventHandler<ScpDownloadEventArgs>(DownloadEvent); // 注册下载事件

            if (args.Length == 1)
            {
                foreach (string path in scmp.RnewFList)
                {
                    string lpath = Utils.GenerateLocalPath(localpath, sinfo.dir, path);
                    if (path.EndsWith("/"))
                    {
                        try
                        {
                            DirectoryInfo dir = new DirectoryInfo(lpath);
                            dir.Create();
                            scpcnt.scp.Download(path, dir);
                        }
                        catch (Exception e)
                        {
                            Utils.ErrorLog(e.Message);
                            scpcnt.DisConnect();
                            return;
                        }
                    }
                    else
                    {
                        try
                        {
                            FileInfo file = new FileInfo(lpath);
                            scpcnt.scp.Download(path, file);
                        }
                        catch (Exception e)
                        {
                            Utils.ErrorLog(e.Message);
                            scpcnt.DisConnect();
                            return;
                        }
                    }
                }
                foreach (string path in scmp.RmodifyList)
                {
                    string lpath = Utils.GenerateLocalPath(localpath, sinfo.dir, path);
                    try
                    {
                        FileInfo file = new FileInfo(lpath);
                        scpcnt.scp.Download(path, file);
                    }
                    catch (Exception e)
                    {
                        Utils.ErrorLog(e.Message);
                        scpcnt.DisConnect();
                        return;
                    }
                }
                Utils.SuccessLog(this.DoCount + " files have been downloaded.");
            }
            else
            {
                if (args[1].Equals("-a"))
                {
                    foreach (string path in scmp.RnewFList)
                    {
                        string lpath = Utils.GenerateLocalPath(localpath, sinfo.dir, path);
                        if (path.EndsWith("/"))
                        {
                            try
                            {
                                DirectoryInfo dir = new DirectoryInfo(lpath);
                                dir.Create();
                                scpcnt.scp.Download(path, dir);
                            }
                            catch (Exception e)
                            {
                                Utils.ErrorLog(e.Message);
                                scpcnt.DisConnect();
                                return;
                            }
                        }
                        else
                        {
                            try
                            {
                                FileInfo file = new FileInfo(lpath);
                                scpcnt.scp.Download(path, file);
                            }
                            catch (Exception e)
                            {
                                Utils.ErrorLog(e.Message);
                                scpcnt.DisConnect();
                                return;
                            }
                        }
                    }
                    Utils.SuccessLog(this.DoCount + " files have been downloaded.");
                }
                else
                {
                    foreach (string path in scmp.RmodifyList)
                    {
                        string lpath = Utils.GenerateLocalPath(localpath, sinfo.dir, path);
                        try
                        {
                            FileInfo file = new FileInfo(lpath);
                            scpcnt.scp.Download(path, file);
                        }
                        catch (Exception e)
                        {
                            Utils.ErrorLog(e.Message);
                            scpcnt.DisConnect();
                            return;
                        }
                    }
                    Utils.SuccessLog(this.DoCount + " files have been downloaded.");
                }
            }
            scpcnt.DisConnect();
        }

        private string CurFile = null;
        private int DoCount = 0;
        private void DownloadEvent(object sender, ScpDownloadEventArgs e)
        {
            if (!e.Filename.Equals(CurFile))
            {
                System.Console.WriteLine("downloading " + e.Filename);
                CurFile = e.Filename;
                DoCount ++;
            }
        }
    }
}